import Heap from './Heap.js'

class AStar {

    /**
     * 
     * @param {Integer} xCount x轴最大值
     * @param {Integer} yCount y轴最大值
     * @param {Array<Node>} oblist 障碍节点列表（Node）
     */
    constructor (xCount, yCount, oblist = []) {
        this.xCount = xCount
        this.yCount = yCount
        this.oblist = oblist
        this.open = null
        this.close = []
        this.exist = []
    }

    is_exist(node) {

    }


    search(start, target) {
        console.log('search');
        console.log(start, target);
        let {open, close, exist} = this
        open = new Heap((x, y) => x.F < y.F)
        console.log(start);
        open.add(start)
        // exist.push(start)

        while (open.size() > 0) {
            console.log(`open size = ${open.size()}`);
            // alert('before' + open.size())
            let curr = open.extract() // F最小
            // console.log(curr);
            // alert(open.size())
            close.push(curr)
            exist.push(curr)
            const neighbors = this.neighbors(curr)
            // console.log(neighbors);
            for (let node of neighbors) {
                // console.log(node);
                if (node.x === target.x && node.y === target.y) {
                    node.parent = curr
                    // console.log(node);
                    const nodeNew = new Node(node.x, node.y)
                    // curr.nextDirection = node.dir
                    nodeNew.init(curr, target)
                    console.log(nodeNew);
                    return nodeNew // 找到了
                }

                // console.log(curr);
                // console.log(this.exist);
                let flag = this.exist.every(n => {
                //    console.log(n, node, node.x != n.x && node.y != n.y);
                    return  node.x !== n.x || node.y !== n.y
                })
                // console.log(flag);
                if (flag) {
                    // alert(flag)
                    // console.log(node);
                    let nodeNew = new Node(node.x, node.y)
                    // curr.nextDirection = node.dir
                    nodeNew.init(curr, target)
                    // console.log(nodeNew);
                    // console.warn('add', nodeNew);
                    open.add(nodeNew)
                    exist.push(nodeNew)
                    // close.add(node)
                }
                
            }
        }
        console.log('return null');
        return null
    }

    neighbors(node) {
        const {x, y} = node
        const oblist = this.oblist
        const loclist = [
            {dir: 'up', x: x, y: y - 1}, // 上
            {dir: 'right', x: x + 1, y: y}, // 右
            {dir: 'down', x: x, y: y + 1}, // 下
            {dir: 'left', x: x - 1, y: y}, // 左
        ]

        // 找出上下左右没有障碍的节点
        const idxlist = loclist.filter(loc => {
            return oblist.every(ob => {
                return ob.x !== loc.x || ob.y !== loc.y
            }) && loc.x < this.xCount && loc.y < this.yCount
               && loc.x >= 0 && loc.y >= 0
            //    && (this.close.every(node => {
            //         console.log(node);
            //         return node.x !== loc.x && node.y !== loc.y
            //    }) || true)
        })

        // console.log(node, idxlist);
        return idxlist
    }

    toList(node) {
        const result = []
        let cur = node
        while (cur) {
            result.unshift(cur)
            cur = cur.parent
        }
        return result
    }
}

class Node {
    constructor(x, y, parent = null) {
        this.x = x
        this.y = y
        this.parent = null
        this.G = 0
        this.H = 0
        this.F = 0
        // this.nextDirection = ''
    }

    init(parent, target) {
        this.parent = parent
        this.G = parent.G + 1
        this.H = Math.abs(this.x - target.x) + Math.abs(this.y - target.y)
        this.F = this.G + this.H
    }
}

// const oblist = [
//     new Node(2, 0),
//     new Node(2, 1),
//     new Node(2, 2),
//     new Node(2, 3),
// ]

// const astar = new AStar(5, 5, oblist)

// const r = astar.search(new Node(0, 2), new Node(4, 2))
// console.log(r);

// const dir = []
// const list = []

// let cur = r.parent
// while (cur) {
//     list.push(cur)
//     dir.push(cur.nextDirection)
//     cur = cur.parent

// }

// console.log(dir, list);



// const list = [
//     [1, 1],
//     [2, 1],
//     [3, 1],
//     [4, 1],
//     [5, 1],
//     [6, 1]
// ]
// const node = new Node(1, 2) // 
// const result = new AStar(10, 10).neighbors(node, list)
// console.log(result)


export {
    AStar,
    Node
} 